//
//  OrderedDictionaryTest.swift
//  SwiftTools
//
//  Created by Samuel Richard Magny on 2015-09-15.
//  Copyright © 2015 Samuel Richard Magny. All rights reserved.
//

import XCTest
import SwiftTools

class OrderedDictionaryTest: XCTestCase {

    let keyStrA = "A"
    let keyStrB = "B"
    let keyStrC = "C"
    let keyStrD = "D"
    let keyStrE = "E"
    let valStrA = "Val1"
    let valStrB = "Val2"
    let valStrC = "Val3"
    let valStrD = "Val4"
    let valStrE = "Val5"
    
    override func setUp() {
        super.setUp()
        // Put setup code here. This method is called before the invocation of each test method in the class.
    }
    
    override func tearDown() {
        // Put teardown code here. This method is called after the invocation of each test method in the class.
        super.tearDown()
    }

    func testSingleCRUD() {
        var dict:OrderedDictionary<String, String> = OrderedDictionary()
        XCTAssertEqual(dict.count, 0, "Count is not working properly")
        
        dict[keyStrA] = valStrA
        XCTAssertEqual(dict.count, 1, "Count is not working properly")
        XCTAssertEqual(dict[keyStrA], valStrA, "Getting value (with subscript) is not working properly")
//        XCTAssertEqual(dict.objectForKey(keyStrA), valStrA, "Getting value is not working properly")
        
        dict[keyStrA] = valStrB
        XCTAssertEqual(dict.count, 1, "Count is not working properly")
        XCTAssertEqual(dict[keyStrA], valStrB, "Getting value (with subscript) is not working properly")
//        XCTAssertEqual(dict.objectForKey(keyStrA), valStrB, "Getting value is not working properly")
        
        dict[keyStrA] = nil
        XCTAssertEqual(dict.count, 0, "Count is not working properly")
        XCTAssertNil(dict[keyStrA], "Acessing an in-existant key should return nil")
//        XCTAssertNil(dict.objectForKey(keyStrA), "Acessing an in-existant key should return nil")
    }
    
    
    func testConsecutiveOrdering() {
        var dict:OrderedDictionary<String, String> = OrderedDictionary()
        
        dict[keyStrA] = valStrA
        XCTAssertEqual(dict.count, 1, "Count is not working properly")
        XCTAssertEqual(dict.indexForKey(keyStrA), 0, "Order is not working properly")
        
        dict[keyStrB] = valStrB
        XCTAssertEqual(dict.count, 2, "Count is not working properly")
        XCTAssertEqual(dict.indexForKey(keyStrB), 1, "Order is not working properly")
        
        dict[keyStrC] = valStrC
        XCTAssertEqual(dict.count, 3, "Count is not working properly")
        XCTAssertEqual(dict.indexForKey(keyStrC), 2, "Order is not working properly")
        
        dict[keyStrD] = valStrD
        XCTAssertEqual(dict.count, 4, "Count is not working properly")
        XCTAssertEqual(dict.indexForKey(keyStrD), 3, "Order is not working properly")
        
        XCTAssertEqual(dict.first!.1, valStrA, "func first() is not working properly")
        XCTAssertEqual(dict.last!.1, valStrD, "func last() is not working properly")
    }
    
    func testConsecutiveOrderingWhenRemovingItems() {
        var dict:OrderedDictionary<String, String> = OrderedDictionary()
        
        dict[keyStrA] = valStrA
        dict[keyStrB] = valStrB
        dict[keyStrC] = valStrC
        dict[keyStrD] = valStrD
        dict[keyStrE] = valStrE

        XCTAssertEqual(dict.indexForKey(keyStrA), 0, "A should be 0")
        XCTAssertEqual(dict.indexForKey(keyStrB), 1, "B should be 1")
        XCTAssertEqual(dict.indexForKey(keyStrC), 2, "C should be 2")
        XCTAssertEqual(dict.indexForKey(keyStrD), 3, "D should be 3")
        XCTAssertEqual(dict.indexForKey(keyStrE), 4, "E should be 4")
        
        dict.removeValueForKey(keyStrB)
        XCTAssertEqual(dict.indexForKey(keyStrA), 0, "A should be 0")
        XCTAssertEqual(dict.indexForKey(keyStrC), 1, "C should be 1")
        XCTAssertEqual(dict.indexForKey(keyStrD), 2, "D should be 2")
        XCTAssertEqual(dict.indexForKey(keyStrE), 3, "E should be 3")
        XCTAssertNil(dict[keyStrB], "Acessing an in-existant key should return nil")
        
        dict.removeValueForKey(keyStrA)
        XCTAssertEqual(dict.indexForKey(keyStrC), 0, "C should be 0")
        XCTAssertEqual(dict.indexForKey(keyStrD), 1, "D should be 1")
        XCTAssertEqual(dict.indexForKey(keyStrE), 2, "E should be 2")
        XCTAssertNil(dict[keyStrA], "Acessing an in-existant key should return nil")
        
        dict.removeValueForKey(keyStrE)
        XCTAssertEqual(dict.indexForKey(keyStrC), 0, "C should be 0")
        XCTAssertEqual(dict.indexForKey(keyStrD), 1, "D should be 1")
        XCTAssertNil(dict[keyStrE], "Acessing an in-existant key should return nil")
        
        dict.removeValueForKey(keyStrC)
        XCTAssertEqual(dict.indexForKey(keyStrD), 0, "D should be 0")
        XCTAssertNil(dict[keyStrC], "Acessing an in-existant key should return nil")
    }
    
    func testRemoveAll() {
        var dict:OrderedDictionary<String, String> = OrderedDictionary()
        
        dict[keyStrA] = valStrA
        dict[keyStrB] = valStrB
        dict[keyStrC] = valStrC
        
        dict.removeAll()
        
        XCTAssertEqual(dict.count, 0, "Count is not working properly")
        XCTAssertNil(dict[keyStrA], "Acessing an in-existant key should return nil")
        XCTAssertNil(dict[keyStrB], "Acessing an in-existant key should return nil")
        XCTAssertNil(dict[keyStrC], "Acessing an in-existant key should return nil")
    }
    
    func testForEach() {
        let dict = generateNewUnordered_OrderedDictionary()
        
        for item in dict
        {
            print("Key:" + item.0.debugDescription)
            print("Value:" + item.1.debugDescription)
        }
    }
    
    func testSort() {
        var unorderedDict = generateNewUnordered_OrderedDictionary()
        unorderedDict.sortInPlace({$0.1 < $1.1})
        
        XCTAssertEqual(unorderedDict.indexForKey(keyStrA), 0, "A should be 0")
        XCTAssertEqual(unorderedDict.indexForKey(keyStrB), 1, "B should be 1")
        XCTAssertEqual(unorderedDict.indexForKey(keyStrC), 2, "C should be 2")
        XCTAssertEqual(unorderedDict.indexForKey(keyStrD), 3, "D should be 3")
        XCTAssertEqual(unorderedDict.indexForKey(keyStrE), 4, "E should be 4")
    }
    
    func testRangeReplace() {
        var dict1:OrderedDictionary<String, String> = OrderedDictionary()
        var dict2:OrderedDictionary<String, String> = OrderedDictionary()
        
        dict1[keyStrA] = valStrA
        dict1[keyStrB] = valStrB
        
        dict2[keyStrC] = valStrC
        dict2[keyStrD] = valStrD
        
        dict1.appendContentsOf(dict2)
        
        XCTAssertEqual(dict1.count, 4, "Count should be 4")
        
        XCTAssertEqual(dict1.indexForKey(keyStrA), 0, "A should be 0")
        XCTAssertEqual(dict1.indexForKey(keyStrB), 1, "A should be 1")
        XCTAssertEqual(dict1.indexForKey(keyStrC), 2, "A should be 2")
        XCTAssertEqual(dict1.indexForKey(keyStrD), 3, "A should be 3")
        
    }
    
    
    private func generateNewUnordered_OrderedDictionary()->OrderedDictionary<String, String>
    {
        var dict:OrderedDictionary<String, String> = OrderedDictionary()
        
        dict[keyStrC] = valStrC
        dict[keyStrE] = valStrE
        dict[keyStrA] = valStrA
        dict[keyStrD] = valStrD
        dict[keyStrB] = valStrB
        
        
        return dict
    }

}
